package ms.unicorn.dsl.utils;

import ms.unicorn.dsl.runtime.ExecutionContext;
import ms.unicorn.dsl.unicornDSL.XFunctionDeclaration;


public class ExceptionUtil {
	
	public static final int LEVEL_COMPACT = 0;
	public static final int LEVEL_DUMP_CONTEXT = 1;
	public static final int LEVEL_ORIGIN_CAUSE = 2;
	public static final int LEVEL_ALL_TRACES = 3;
	
	public static int VerboseLevel = 0;
	
	public static String exceptionToString(Throwable e, Throwable cause) {
		if (e instanceof SphynxRuntimeException) { // special presentation for Sphynx
			StringBuilder msg = new StringBuilder();
			msg.append(String.format("Runtime exception (%s): %s\n", cause.getClass().getSimpleName(), cause.getMessage()));				
			ExecutionContext callcontext = ((SphynxRuntimeException) e).getContext();
			if (callcontext != null) {
				msg.append("Trace:\n");
				while (callcontext != null) {						
					XFunctionDeclaration exp = callcontext.getExecutingFunction();			
					String name = exp != null ? exp.getName() + "()" : "<null>";
					msg.append(String.format("\t at %s %s", name, SphynxRuntimeUtil.getLocation(true, callcontext, callcontext.getEvaluatingExpression())));
					if (VerboseLevel >= LEVEL_DUMP_CONTEXT)
						msg.append(String.format(". Context dump: %s\n", callcontext.toString() ));
					else msg.append('\n');
					callcontext = callcontext.getCallerContext();
				}
			}
			return msg.toString();
		}
		return e.getMessage();
	}
	
	public static String handleException(Exception e) {
		// get the deepest exception
		Throwable de = e;
		while (de.getCause() != null) de = de.getCause();
		String msg = null;
		if (de instanceof SphynxRuntimeException)
			msg = exceptionToString(de, de);
		else if (e instanceof SphynxRuntimeException)
			msg = exceptionToString(e, de);
		System.out.println(msg);
		if (VerboseLevel >= LEVEL_ALL_TRACES)
			e.printStackTrace();
		return msg;
	}
	
	
	/*public static void handleException(Exception e) {
		// get the deepest exception
		Throwable de = e;
		while (de.getCause() != null) de = de.getCause();
		
		if (de instanceof SphynxRuntimeException) { // special presentation for Sphynx
			StringBuilder msg = new StringBuilder();
			msg.append(String.format("Runtime error: %s\n", de.getMessage()));				
			ExecutionContext callcontext = ((SphynxRuntimeException) de).getContext();
			if (callcontext != null) {
				msg.append("Trace:\n");
				while (callcontext != null) {						
					XFunctionDeclaration exp = callcontext.getExecutingFunction();
					String name = exp != null ? exp.getName() + "()" : "<null>";
					msg.append(String.format("\t at %s %s. context dump: %s\n", 
							name, 
							SphynxRuntimeUtil.getLocation(true, callcontext, null),
							callcontext.toString()
							));
					callcontext = callcontext.getCallerContext();
				}
			}
			System.out.print(msg.toString());
			e.printStackTrace();
		}
		else
			e.printStackTrace();
	}*/
}
